import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage.metrics import adapted_rand_error, variation_of_information
import cv2
from skfuzzy.cluster import cmeans
import itertools
import scipy
import warnings
warnings.filterwarnings('ignore')
image = imread('bacteries_1.jpg')
image1 = imread('bacteries_2.jpg')
imshow(image);
imshow(image1);
def convert_to_2d(image):
image_2d = image.reshape((-1,3))
image_2d = np.float32(image_2d)
return image_2d
image_2d = convert_to_2d(image)
image1_2d = convert_to_2d(image1)
MAX_ITER = 100
EPSILON = 0.85
CRITERIA = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, MAX_ITER, EPSILON)
ATTEMPTS = 10
CENTERS_METHODS = (cv2.KMEANS_PP_CENTERS, cv2.KMEANS_RANDOM_CENTERS)
CLUSTERS_RANGE = range(1, 11)
def calculate_intracluster_distance_sum(cluster_elements, centroid):
return sum([scipy.spatial.distance.sqeuclidean(centroid, element) for element in cluster_elements])
def get_intercluster_distance(centroid, centers):
# if len(centers) > 1:
# return scipy.spatial.distance.pdist(centers, 'sqeuclidean').min()
return sum([scipy.spatial.distance.sqeuclidean(centroid, centroid_other) for centroid_other in centers])
# else:
# return 0
def xie_benie(segmented_image, centers):
xb = sum([calculate_intracluster_distance_sum(segmented_image[segmented_image == center], center)
for center in centers]) / (
sum([get_intercluster_distance(centroid, centers) for centroid in centers])
* segmented_image.reshape((-1, 3)).shape[0])
return xb
def kmeans_segmentation(image2d, original_image_shape, n_clusters, criteria, attempts, centers_method):
retval, labels, centers = cv2.kmeans(image2d, n_clusters, None, criteria,
attempts, centers_method)
centers = np.uint8(centers)
segmented_data = centers[labels.flatten()]
segmented_image = segmented_data.reshape((original_image_shape))
return segmented_image, centers
def create_segmented_mapping(image2d, original_image_shape, centers_methods, nclusters_range):
mapping = {center: {n: None for n in nclusters_range} for center in centers_methods}
for center_method, nclusters in itertools.product(centers_methods, nclusters_range):
mapping[center_method][nclusters] = kmeans_segmentation(image2d, original_image_shape,
nclusters, criteria=CRITERIA,
attempts=ATTEMPTS,
centers_method=center_method)
return mapping
segmented_images_kmeans_mapping = create_segmented_mapping(image_2d, image.shape, CENTERS_METHODS, CLUSTERS_RANGE)
segmented_images1_kmeans_mapping = create_segmented_mapping(image1_2d, image1.shape, CENTERS_METHODS,
CLUSTERS_RANGE)
fig, axs = plt.subplots(nrows=10, ncols=2, figsize=(20, 50))
for i, nclusters in enumerate(CLUSTERS_RANGE):
for j, center_method in enumerate(CENTERS_METHODS):
axs[i][j].imshow(segmented_images_kmeans_mapping.get(center_method).get(nclusters)[0], aspect='auto');
axs[i][0].set_title('PP Centers, {} clusters'.format(nclusters))
axs[i][1].set_title('Random Centers, {} clusters'.format(nclusters))
fig, axs = plt.subplots(nrows=10, ncols=2, figsize=(20, 50))
for i, nclusters in enumerate(CLUSTERS_RANGE):
for j, center_method in enumerate(CENTERS_METHODS):
axs[i][j].imshow(segmented_images1_kmeans_mapping.get(center_method).get(nclusters)[0], aspect='auto');
axs[i][0].set_title('PP Centers, {} clusters'.format(nclusters))
axs[i][1].set_title('Random Centers, {} clusters'.format(nclusters))
xie_beni_values = [[xie_benie(*segmented_images_kmeans_mapping.get(center_method).get(nclusters))
for nclusters in CLUSTERS_RANGE] for center_method in CENTERS_METHODS]
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10, 6))
center_methods_titles = ('PP Centers', 'Random Centers')
for i in range(2):
axs[i].plot(xie_beni_values[i])
axs[i].set_title('Xie-Beni index, {} cluster centers'.format(center_methods_titles[i]))
axs[i].set_xlabel('Number of cluster')
xie_beni_values_image1 = [[xie_benie(*segmented_images1_kmeans_mapping.get(center_method).get(nclusters))
for nclusters in CLUSTERS_RANGE] for center_method in CENTERS_METHODS]
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10, 6))
center_methods_titles = ('PP Centers', 'Random Centers')
for i in range(2):
axs[i].plot(xie_beni_values_image1[i])
axs[i].set_title('Xie-Beni index, {} cluster centers'.format(center_methods_titles[i]))
axs[i].set_xlabel('Number of cluster')
def get_segmentation_metrics(original_image, segmented_image):
error, precision, recall = adapted_rand_error(original_image, segmented_image)
splits, merges = variation_of_information(original_image, segmented_image)
return error, precision, recall, splits, merges
metrics_image = [[get_segmentation_metrics(image,
segmented_images_kmeans_mapping.get(center_method).get(nclusters)[0])
for nclusters in CLUSTERS_RANGE] for center_method in CENTERS_METHODS]
fig, axs = plt.subplots(nrows=5, ncols=2, figsize=(10, 30))
center_methods_titles = ('PP Centers', 'Random Centers')
errors_titles = ('Error', 'Precision', 'Recall', 'False splits', 'False merges')
for j, i in itertools.product(range(5), range(2)):
metrics = [[metric[j] for metric in metrics] for metrics in metrics_image]
axs[j][i].plot(metrics[i])
axs[j][i].set_title('{}, {} cluster centers'.format(errors_titles[j],center_methods_titles[i]))
axs[j][i].set_xlabel('Number of cluster')
metrics_image1 = [[get_segmentation_metrics(image1,
segmented_images1_kmeans_mapping.get(center_method).get(nclusters)[0])
for nclusters in CLUSTERS_RANGE] for center_method in CENTERS_METHODS]
fig, axs = plt.subplots(nrows=5, ncols=2, figsize=(10, 30))
center_methods_titles = ('PP Centers', 'Random Centers')
errors_titles = ('Error', 'Precision', 'Recall', 'False splits', 'False merges')
for j, i in itertools.product(range(5), range(2)):
metrics = [[metric[j] for metric in metrics] for metrics in metrics_image1]
axs[j][i].plot(metrics[i])
axs[j][i].set_title('{}, {} cluster centers'.format(errors_titles[j],center_methods_titles[i]))
axs[j][i].set_xlabel('Number of cluster')
def fuzzy_cmeans_segmentation(image2d, original_shape, n_clusters, power, eps, max_iter):
centers, fuzzy_matrix = cmeans(image2d.T, n_clusters, power, eps, max_iter, seed=42)[:2]
centers = np.uint8(centers)
segmented_image = centers[fuzzy_matrix.argmax(axis=0)]
segmented_image = segmented_image.reshape(original_shape)
return segmented_image, fuzzy_matrix, centers
M = 2
segmented_images_fuzzy = [fuzzy_cmeans_segmentation(image_2d, image.shape, nclusters, M, EPSILON, MAX_ITER)
for nclusters in CLUSTERS_RANGE]
fig, axs = plt.subplots(nrows=len(CLUSTERS_RANGE), ncols=1, figsize=(10, 50))
for i, nclusters in enumerate(CLUSTERS_RANGE):
axs[i].imshow(segmented_images_fuzzy[i][0], aspect='auto');
axs[i].set_title('Fuzzy C-Means, {} clusters'.format(nclusters))
segmented_images1_fuzzy = [fuzzy_cmeans_segmentation(image1_2d, image1.shape, nclusters, M, EPSILON, MAX_ITER)
for nclusters in CLUSTERS_RANGE]
fig, axs = plt.subplots(nrows=len(CLUSTERS_RANGE), ncols=1, figsize=(10, 50))
for i, nclusters in enumerate(CLUSTERS_RANGE):
axs[i].imshow(segmented_images1_fuzzy[i][0], aspect='auto');
axs[i].set_title('Fuzzy C-Means, {} clusters'.format(nclusters))
xie_beni_values_fuzzy_cmeans = [xie_benie(segmented_images_fuzzy[i][0], segmented_images_fuzzy[i][2])
for i, nclusters in enumerate(CLUSTERS_RANGE)]
plt.plot(xie_beni_values_fuzzy_cmeans)
plt.title('Xie-Beni index')
plt.xlabel('Number of cluster');
xie_beni_values_fuzzy_cmeans_image1 = [xie_benie(segmented_images1_fuzzy[i][0], segmented_images_fuzzy[i][2])
for i, nclusters in enumerate(CLUSTERS_RANGE)]
plt.plot(xie_beni_values_fuzzy_cmeans_image1)
plt.title('Xie-Beni index')
plt.xlabel('Number of cluster');
metrics_image_fuzzy = [get_segmentation_metrics(image, segmented_image[0]) for segmented_image
in segmented_images_fuzzy]
fig, axs = plt.subplots(nrows=5, ncols=1, figsize=(10, 30))
errors_titles = ('Error', 'Precision', 'Recall', 'False splits', 'False merges')
for i in range(5):
metrics = [metrics[i] for metrics in metrics_image_fuzzy]
axs[i].plot(metrics)
axs[i].set_title('{}'.format(errors_titles[i]))
axs[i].set_xlabel('Number of cluster')
metrics_image1_fuzzy = [get_segmentation_metrics(image1, segmented_image[0]) for segmented_image
in segmented_images1_fuzzy]
fig, axs = plt.subplots(nrows=5, ncols=1, figsize=(10, 30))
errors_titles = ('Error', 'Precision', 'Recall', 'False splits', 'False merges')
for i in range(5):
metrics = [metrics[i] for metrics in metrics_image1_fuzzy]
axs[i].plot(metrics)
axs[i].set_title('{}'.format(errors_titles[i]))
axs[i].set_xlabel('Number of cluster')